package icu.feigroup.infrastructure.adapter.repository;

import com.alibaba.fastjson.JSON;
import icu.feigroup.domain.trade.adapter.repository.ITradeRepository;
import icu.feigroup.domain.trade.model.aggregate.GroupBuyOrderAggregate;
import icu.feigroup.domain.trade.model.aggregate.GroupBuyTeamSettlementAggregate;
import icu.feigroup.domain.trade.model.entity.*;
import icu.feigroup.domain.trade.model.valobj.GroupBuyProgressVO;
import icu.feigroup.domain.trade.model.valobj.TradeOrderStatusEnumVO;
import icu.feigroup.infrastructure.dao.GroupActivityMapper;
import icu.feigroup.infrastructure.dao.GroupOrderListMapper;
import icu.feigroup.infrastructure.dao.GroupOrderMapper;
import icu.feigroup.infrastructure.dao.NotifyTaskMapper;
import icu.feigroup.infrastructure.dao.po.GroupActivity;
import icu.feigroup.infrastructure.dao.po.GroupOrder;
import icu.feigroup.infrastructure.dao.po.GroupOrderList;
import icu.feigroup.infrastructure.dao.po.NotifyTask;
import icu.feigroup.infrastructure.dcc.DCCService;
import icu.feigroup.types.common.Constants;
import icu.feigroup.types.enums.ActivityStatusEnumVO;
import icu.feigroup.types.enums.GroupBuyOrderEnumVO;
import icu.feigroup.types.enums.ResponseCode;
import icu.feigroup.types.exception.AppException;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * projectName:icu.feigroup.domain.trade.adapter.repository
 *
 * @author 飞
 * @since 2025/2/23 12:19
 * description:
 */
@Repository
public class TradeRepository implements ITradeRepository {
    @Resource
    private GroupOrderMapper groupOrderMapper;
    @Resource
    private GroupOrderListMapper groupOrderListMapper;
    @Resource
    private GroupActivityMapper groupActivityMapper;
    @Resource
    private NotifyTaskMapper notifyTaskMapper;
    @Resource
    private DCCService dccService;
    @Override
    public MarketPayOrderEntity queryPayMarketPayOrderByOutTradeNo(String userId, String outTradeNo) {
        GroupOrderList groupOrderListReq = new GroupOrderList();
        groupOrderListReq.setUserId(userId);
        groupOrderListReq.setOutTradeNo(outTradeNo);

        GroupOrderList groupOrderListRes = groupOrderListMapper.queryGroupOrderRecordByOutTradeNo(groupOrderListReq);
        if (groupOrderListRes == null) return null;
        return MarketPayOrderEntity.builder()
                .teamId(groupOrderListRes.getTeamId())
                .orderId(groupOrderListRes.getOrderId())
                .deductionPrice(groupOrderListRes.getDeductionPrice())
                .tradeOrderStatusEnumVO(TradeOrderStatusEnumVO.valueOf(groupOrderListRes.getStatus()))
                .build();
    }

    @Override
    public GroupBuyProgressVO queryGroupBuyProgress(String teamId) {
        if (StringUtils.isBlank(teamId)) return null;
        GroupOrder groupOrderRes = groupOrderMapper.queryGroupProgress(teamId);
        if (groupOrderRes==null) return null;
        return GroupBuyProgressVO.builder()
                .targetCount(groupOrderRes.getTargetCount())
                .completeCount(groupOrderRes.getCompleteCount())
                .lockCount(groupOrderRes.getLockCount())
                .build();
    }

    @Transactional(timeout = 500)
    @Override
    public MarketPayOrderEntity lockMarketPayOrder(GroupBuyOrderAggregate groupBuyOrderAggregate) {
        if (groupBuyOrderAggregate == null) return null;
        UserEntity userEntity = groupBuyOrderAggregate.getUserEntity();
        PayActivityEntity payActivityEntity = groupBuyOrderAggregate.getPayActivityEntity();
        PayDiscountEntity payDiscountEntity = groupBuyOrderAggregate.getPayDiscountEntity();
        Integer count = groupBuyOrderAggregate.getUserTakeOrderCount();

        //判断是否有团 teamId 空→新团
        String teamId = payActivityEntity.getTeamId();
        if (StringUtils.isBlank(teamId)){
            // 使用 RandomStringUtils.randomNumeric 替代公司里使用的雪花算法UUID
            teamId = RandomStringUtils.randomNumeric(8);
            Date currentTime = new Date();
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(currentTime);
            calendar.add(Calendar.MINUTE, payActivityEntity.getValidTime());

            GroupOrder groupOrder = GroupOrder.builder()
                    .teamId(teamId)
                    .activityId(payActivityEntity.getActivityId())
                    .source(payDiscountEntity.getSource())
                    .channel(payDiscountEntity.getChannel())
                    .originalPrice(payDiscountEntity.getOriginalPrice())
                    .deductionPrice(payDiscountEntity.getDeductionPrice())
                    .payPrice(payDiscountEntity.getPayPrice())
                    .targetCount(payActivityEntity.getTargetCount())
                    .completeCount(0)
                    .lockCount(1)
                    .validStartTime(currentTime)
                    .validEndTime(calendar.getTime())
                    .notifyUrl(payDiscountEntity.getNotifyUrl())
                    .build();

            //记录
            groupOrderMapper.insert(groupOrder);
        }else {
            //更新记录 - 如果更新记录不等于1，则表示拼团已满，抛出异常
            int updated = groupOrderMapper.updateAddLockCount(teamId);
            if (updated!=1){
                throw new AppException(ResponseCode.E005.getCode());
            }
        }
        // 使用 RandomStringUtils.randomNumeric 替代公司里使用的雪花算法UUID
        String orderId = RandomStringUtils.randomNumeric(12);
        GroupOrderList groupBuyOrderListReq = GroupOrderList.builder()
                .userId(userEntity.getUserId())
                .teamId(teamId)
                .orderId(orderId)
                .activityId(payActivityEntity.getActivityId())
                .startTime(payActivityEntity.getStartTime())
                .endTime(payActivityEntity.getEndTime())
                .goodsId(payDiscountEntity.getGoodsId())
                .source(payDiscountEntity.getSource())
                .channel(payDiscountEntity.getChannel())
                .originalPrice(payDiscountEntity.getOriginalPrice())
                .deductionPrice(payDiscountEntity.getDeductionPrice())
                .status(TradeOrderStatusEnumVO.CREATE.getCode())
                .outTradeNo(payDiscountEntity.getOutTradeNo())
                .bizId(payDiscountEntity.getGoodsId()+ Constants.UNDERLINE +userEntity.getUserId()+Constants.UNDERLINE+(count+1))
                .build();

        try {
            // 写入拼团记录
            groupOrderListMapper.insert(groupBuyOrderListReq);
        } catch (DuplicateKeyException e) {
            //唯一索引冲突
            throw new AppException(ResponseCode.INDEX_EXCEPTION);
        }

        return MarketPayOrderEntity.builder()
                .teamId(teamId)
                .orderId(orderId)
                .deductionPrice(groupBuyOrderListReq.getDeductionPrice())
                .tradeOrderStatusEnumVO(TradeOrderStatusEnumVO.CREATE)
                .build();
    }

    @Override
    public GroupBuyActivityEntity queryGroupBuyActivityByActivityId(Long activityId) {
        GroupActivity groupActivity = groupActivityMapper.queryGroupBuyActivityByActivityId(activityId);
        return GroupBuyActivityEntity.builder()
                .activityId(groupActivity.getActivityId())
                .activityName(groupActivity.getActivityName())
                .discountId(groupActivity.getDiscountId())
                .groupType(groupActivity.getGroupType())
                .takeLimitCount(groupActivity.getTakeLimitCount())
                .target(groupActivity.getTarget())
                .validTime(groupActivity.getValidTime())
                .status(ActivityStatusEnumVO.valueOf(groupActivity.getStatus()))
                .startTime(groupActivity.getStartTime())
                .endTime(groupActivity.getEndTime())
                .tagId(groupActivity.getTagId())
                .tagScope(groupActivity.getTagScope())
                .build();

    }

    @Override
    public Integer queryOrderCountByActivityId(Long activityId, String userId) {
        GroupOrderList groupOrderListReq = new GroupOrderList();
        groupOrderListReq.setActivityId(activityId);
        groupOrderListReq.setUserId(userId);
        return groupOrderListMapper.queryOrderCountByActivityId(groupOrderListReq);
    }

    @Override
    public GroupBuyTeamEntity queryGroupBuyTeamByTeamId(String teamId) {
        GroupOrder groupOrder = groupOrderMapper.queryGroupBuyTeamByTeamId(teamId);
        if (groupOrder==null) return null;
        return GroupBuyTeamEntity.builder()
                .teamId(teamId)
                .activityId(groupOrder.getActivityId())
                .targetCount(groupOrder.getTargetCount())
                .completeCount(groupOrder.getCompleteCount())
                .lockCount(groupOrder.getLockCount())
                .status(GroupBuyOrderEnumVO.valueOf(groupOrder.getStatus()))
                .validStartTime(groupOrder.getValidStartTime())
                .validEndTime(groupOrder.getValidEndTime())
                .notifyUrl(groupOrder.getNotifyUrl())
                .build();
    }

    @Transactional(timeout = 500)
    @Override
    public boolean settlementMarketPayOrder(GroupBuyTeamSettlementAggregate groupBuyTeamSettlementAggregate) {
        UserEntity userEntity = groupBuyTeamSettlementAggregate.getUserEntity();
        GroupBuyTeamEntity groupBuyTeamEntity = groupBuyTeamSettlementAggregate.getGroupBuyTeamEntity();
        TradePaySuccessEntity tradePaySuccessEntity = groupBuyTeamSettlementAggregate.getTradePaySuccessEntity();

        //1.更新拼团订单明细状态
        GroupOrderList groupOrderListReq = new GroupOrderList();
        groupOrderListReq.setUserId(userEntity.getUserId());
        groupOrderListReq.setOutTradeNo(tradePaySuccessEntity.getOutTradeNo());
        groupOrderListReq.setOutTradeTime(tradePaySuccessEntity.getOutTradeTime());
        int updateOrderListStatusCount = groupOrderListMapper.updateOrderStatusToComplete(groupOrderListReq);
        if (updateOrderListStatusCount!=1){
            throw new AppException(ResponseCode.UPDATE_ZERO);
        }

        // 2. 更新拼团达成数量
        int updateAddCount = groupOrderMapper.updateAddCompleteCount(groupBuyTeamEntity.getTeamId());
        if (1 != updateAddCount) {
            throw new AppException(ResponseCode.UPDATE_ZERO);
        }

        //3.更新拼团完成状态
        if (groupBuyTeamEntity.getTargetCount()-groupBuyTeamEntity.getCompleteCount()==1) {
            int updateOrderStatusCount = groupOrderMapper.updateOrderStatusToComplete(groupBuyTeamEntity.getTeamId());
            if (1 != updateOrderStatusCount) {
                throw new AppException(ResponseCode.UPDATE_ZERO);
            }

            List<String> outTradeNoList = groupOrderListMapper.queryGroupBuyCompleteOrderOutTradeNoListByTeamId(groupBuyTeamEntity.getTeamId());

            NotifyTask notifyTask = new NotifyTask();
            notifyTask.setActivityId(groupBuyTeamEntity.getActivityId());
            notifyTask.setTeamId(groupBuyTeamEntity.getTeamId());
            notifyTask.setNotifyUrl(groupBuyTeamEntity.getNotifyUrl());
            notifyTask.setNotifyCount(0);
            notifyTask.setNotifyStatus(0);
            notifyTask.setParameterJson(JSON.toJSONString(new HashMap<String, Object>() {{
                put("teamId", groupBuyTeamEntity.getTeamId());
                put("outTradeNoList", outTradeNoList);
            }}));

            notifyTaskMapper.insert(notifyTask);
            return true;
        }
        return false;
    }

    @Override
    public boolean isSCBlackIntercept(String source, String channel) {
        return dccService.isSCBlackIntercept(source,channel);
    }

    @Override
    public MarketPayOrderEntity queryMarketPayOrderEntityByOutTradeNo(String userId, String outTradeNo) {
        GroupOrderList groupOrderListReq = new GroupOrderList();
        groupOrderListReq.setUserId(userId);
        groupOrderListReq.setOutTradeNo(outTradeNo);

        GroupOrderList groupOrderListRes = groupOrderListMapper.queryGroupBuyOrderRecordByOutTradeNo(groupOrderListReq);
        if (groupOrderListRes==null){
            return null;
        }

        return MarketPayOrderEntity.builder()
                .teamId(groupOrderListRes.getTeamId())
                .orderId(groupOrderListRes.getOrderId())
                .deductionPrice(groupOrderListRes.getDeductionPrice())
                .tradeOrderStatusEnumVO(TradeOrderStatusEnumVO.valueOf(groupOrderListRes.getStatus()))
                .build();
    }

    @Override
    public int updateNotifyTaskStatusSuccess(String teamId) {
        return notifyTaskMapper.updateNotifyTaskStatusSuccess(teamId);
    }

    @Override
    public int updateNotifyTaskStatusError(String teamId) {
        return notifyTaskMapper.updateNotifyTaskStatusError(teamId);
    }

    @Override
    public int updateNotifyTaskStatusRetry(String teamId) {
        return notifyTaskMapper.updateNotifyTaskStatusRetry(teamId);
    }

    @Override
    public List<NotifyTaskEntity> queryUnExecutedNotifyTaskList() {
        List<NotifyTask> notifyTaskList = notifyTaskMapper.queryUnExecutedNotifyTaskList();
        if (notifyTaskList.isEmpty()){
            return new ArrayList<>();
        }

        List<NotifyTaskEntity> notifyTaskEntities = new ArrayList<>();
        for (NotifyTask notifyTask : notifyTaskList) {
            NotifyTaskEntity notifyTaskEntity = NotifyTaskEntity.builder()
                    .teamId(notifyTask.getTeamId())
                    .notifyUrl(notifyTask.getNotifyUrl())
                    .notifyCount(notifyTask.getNotifyCount())
                    .parameterJson(notifyTask.getParameterJson())
                    .build();
            notifyTaskEntities.add(notifyTaskEntity);
        }
        return notifyTaskEntities;
    }

    @Override
    public List<NotifyTaskEntity> queryUnExecutedNotifyTaskList(String teamId) {
        NotifyTask notifyTask = notifyTaskMapper.queryUnExecutedNotifyTaskByTeamId(teamId);
        if (null == notifyTask) return new ArrayList<>();
        return Collections.singletonList(NotifyTaskEntity.builder()
                .teamId(notifyTask.getTeamId())
                .notifyUrl(notifyTask.getNotifyUrl())
                .notifyCount(notifyTask.getNotifyCount())
                .parameterJson(notifyTask.getParameterJson())
                .build());
    }
}
